﻿using Framework;
using TrueSync;
using System.Collections.Generic;

public enum JumpTargetTypeEnum
{
    SkillStreamInCurrentSkillGroup,
    SkillStreamInOtherSkillGroup,
    CallbackEvent
}

public enum JumpConditionTypeEnum
{
    DirectJump,
    StimulateJump,
    LengthJump,
    HeightJump,
    StateJump,//状态机跳转
    StatusJump,//状态跳转
    PropertiesJump,//属性跳转
    ChargeJump,
}

public class JumpTarget
{
    public JumpTargetTypeEnum JumpTargetType;
    //当前技能的技能流ID
    public int SkillStreamIDInCurrentSkillGroup;
    //跳转到指定技能组的指定技能流
    public int TargetSkillGroupID;
    public int SkillStreamIDInTargetSkillGroup;
    //事件回调ID
    public int CallbackEventID;

    public virtual void Serialize(EByte ms)
    {
        ms.WriteInt((int)JumpTargetType);
        if(JumpTargetType == JumpTargetTypeEnum.SkillStreamInCurrentSkillGroup)
        {
            ms.WriteInt(SkillStreamIDInCurrentSkillGroup);
        }
        else if(JumpTargetType == JumpTargetTypeEnum.SkillStreamInOtherSkillGroup)
        {
            ms.WriteInt(TargetSkillGroupID);
            ms.WriteInt(SkillStreamIDInTargetSkillGroup);
        }
        else if(JumpTargetType == JumpTargetTypeEnum.CallbackEvent)
        {
            ms.WriteInt(CallbackEventID);
        }
    }

    public virtual void Deserialize(EByte ms)
    {
        JumpTargetType = (JumpTargetTypeEnum)ms.ReadInt();
        if(JumpTargetType == JumpTargetTypeEnum.SkillStreamInCurrentSkillGroup)
        {
            SkillStreamIDInCurrentSkillGroup = ms.ReadInt();
        }
        else if(JumpTargetType == JumpTargetTypeEnum.SkillStreamInOtherSkillGroup)
        {
            TargetSkillGroupID = ms.ReadInt();
            SkillStreamIDInTargetSkillGroup = ms.ReadInt();
        }
        else if(JumpTargetType == JumpTargetTypeEnum.CallbackEvent)
        {
            CallbackEventID = ms.ReadInt();
        }
    }
}

public class IntervalJumpTarget:JumpTarget
{
    public int LowerBoundary, UpperBoundary;

    public override void Serialize(EByte ms)
    {
        base.Serialize(ms);
        ms.WriteInt(LowerBoundary);
        ms.WriteInt(UpperBoundary);
    }

    public override void Deserialize(EByte ms)
    {
        base.Deserialize(ms);
        LowerBoundary = ms.ReadInt();
        UpperBoundary = ms.ReadInt();
    }
}


public class JumpEventEffector : BaseEventEffector
{
    public JumpConditionTypeEnum JumpConditionType;

    public JumpTarget JumpTarget;//除了属性跳转和蓄力跳转之外都用这个
    public List<StimulateTypeEnum> StimulateJumpCondition;
    public bool IsGreaterOrEqual;
    public FP LengthJumpCondition;
    public FP HeightJumpCondition;
    //状态跳转，状态机跳转共用
    public bool IsCheckSelf;
    //状态跳转条件
    public bool IsContainStatusJump;
    public List<int> StatusIDs;
    //状态机跳转
    public List<StateEnum> StateMachineEnums;
    public string PropertyName;
    //属性跳转和蓄力跳转都用到这个
    public List<IntervalJumpTarget> IntervalJumpTargets;

    public override void DoEvent(ObjHandle<LogicEntity> owner, params object[] allParams)
    {
        JumpTarget target = null;
        switch (JumpConditionType)
        {
            case JumpConditionTypeEnum.DirectJump:
                target = JumpTarget;
                break;
            case JumpConditionTypeEnum.StimulateJump:
                Stimulate stimulate = allParams.Length > 0 ? (Stimulate)allParams[0] : null;
                if(stimulate != null)
                {
                    if(StimulateJumpCondition.Contains(stimulate.StimulateType))
                    {
                        target = JumpTarget;
                    }
                }
                break;
            case JumpConditionTypeEnum.LengthJump:
                ObjHandle<LogicEntity> myEntity = owner;
                ObjHandle<LogicEntity> otherEntity = FightGame.Instance.GetRivalEntity(owner.handle.PlayerID);
                if(
                    (IsGreaterOrEqual && (owner.handle.GetLogicComponent<LogicMoveComponent>().Position - otherEntity.handle.GetLogicComponent<LogicMoveComponent>().Position).magnitude >= LengthJumpCondition) ||
                    (!IsGreaterOrEqual && (owner.handle.GetLogicComponent<LogicMoveComponent>().Position - otherEntity.handle.GetLogicComponent<LogicMoveComponent>().Position).magnitude <= LengthJumpCondition)
                  )
                {
                    target = JumpTarget;
                }
                break;
            case JumpConditionTypeEnum.HeightJump:
                if (
                     (IsGreaterOrEqual && owner.handle.GetLogicComponent<LogicMoveComponent>().Position.y >= HeightJumpCondition) ||
                     (!IsGreaterOrEqual && owner.handle.GetLogicComponent<LogicMoveComponent>().Position.y <= HeightJumpCondition)
                   )
                {
                    target = JumpTarget;
                }
                break;
            case JumpConditionTypeEnum.StatusJump:
                ObjHandle<LogicEntity> statusJumpTarget = IsCheckSelf ? owner : FightGame.Instance.GetRivalEntity(owner.handle.PlayerID);
                //TODO:status还没有实现
                break;
            case JumpConditionTypeEnum.StateJump:
                ObjHandle<LogicEntity> stateJumpTarget = IsCheckSelf ? owner : FightGame.Instance.GetRivalEntity(owner.handle.PlayerID);
                StateEnum stateEnum = stateJumpTarget.handle.GetLogicComponent<LogicStateMachineComponent>().CurrentState.StateName;
                if(StateMachineEnums.Contains(stateEnum))
                {
                    target = JumpTarget;
                }
                break;
            case JumpConditionTypeEnum.PropertiesJump:
                LogicStatusComponent statusComponent = owner.handle.GetLogicComponent<LogicStatusComponent>();
                int value = statusComponent[PropertyName];
                for(int i = 0; i < IntervalJumpTargets.Count; i++)
                {
                    IntervalJumpTarget intervalTarget = IntervalJumpTargets[i];
                    if(value >= intervalTarget.LowerBoundary && value <= intervalTarget.UpperBoundary)
                    {
                        target = intervalTarget;
                        break;
                    }
                }
                break;
            case JumpConditionTypeEnum.ChargeJump:
                if(allParams.Length > 0)
                {
                    int chargetFrames = (int)allParams[0];
                    for (int i = 0; i < IntervalJumpTargets.Count; i++)
                    {
                        IntervalJumpTarget intervalTarget = IntervalJumpTargets[i];
                        if (chargetFrames >= intervalTarget.LowerBoundary && chargetFrames <= intervalTarget.UpperBoundary)
                        {
                            target = intervalTarget;
                            break;
                        }
                    }
                }
                break;
        }

        //跳转失败,直接返回
        if (target == null)
            return;

        switch(target.JumpTargetType)
        {
            case JumpTargetTypeEnum.SkillStreamInCurrentSkillGroup:
                LogicStateMachineComponent stateMachineComponent = owner.handle.GetLogicComponent<LogicStateMachineComponent>();
                stateMachineComponent.ChangeToSkillStream(target.SkillStreamIDInCurrentSkillGroup);
                break;
            case JumpTargetTypeEnum.SkillStreamInOtherSkillGroup:
                LogicSkillGroupComponent skillGroupComponent = owner.handle.GetLogicComponent<LogicSkillGroupComponent>();
                skillGroupComponent.UseSkillGroup(target.TargetSkillGroupID, target.SkillStreamIDInTargetSkillGroup);
                break;
            case JumpTargetTypeEnum.CallbackEvent:
                LogicEventComponent eventComponent = owner.handle.GetLogicComponent<LogicEventComponent>();
                eventComponent.CallEvent(target.CallbackEventID);
                break;
        }
    }

    public override void OnDestroy()
    {
    }

    public override void Serialize(EByte ms)
    {
        ms.WriteInt((int)JumpConditionType);
        switch(JumpConditionType)
        {
            case JumpConditionTypeEnum.DirectJump:
                JumpTarget.Serialize(ms);
                break;
            case JumpConditionTypeEnum.StimulateJump:
                JumpTarget.Serialize(ms);
                ms.WriteInt(StimulateJumpCondition.Count);
                for(int i = 0; i < StimulateJumpCondition.Count; i++)
                {
                    ms.WriteInt((int)StimulateJumpCondition[i]);
                }
                break;
            case JumpConditionTypeEnum.LengthJump:
                JumpTarget.Serialize(ms);
                ms.WriteInt(IsGreaterOrEqual ? 1 : 0);
                ms.WriteLong(LengthJumpCondition.RawValue);
                break;
            case JumpConditionTypeEnum.HeightJump:
                JumpTarget.Serialize(ms);
                ms.WriteInt(IsGreaterOrEqual ? 1 : 0);
                ms.WriteLong(HeightJumpCondition.RawValue);
                break;
            case JumpConditionTypeEnum.StatusJump:
                JumpTarget.Serialize(ms);
                ms.WriteInt(IsCheckSelf ? 1 : 0);
                ms.WriteInt(IsContainStatusJump ? 1 : 0);
                ms.WriteInt(StatusIDs.Count);
                for(int i = 0; i < StatusIDs.Count; i++)
                {
                    ms.WriteInt(StatusIDs[i]);
                }
                break;
            case JumpConditionTypeEnum.StateJump:
                JumpTarget.Serialize(ms);
                ms.WriteInt(IsCheckSelf ? 1 : 0);
                ms.WriteInt(StateMachineEnums.Count);
                for (int i = 0; i < StateMachineEnums.Count; i++)
                {
                    ms.WriteInt((int)StateMachineEnums[i]);
                }
                break;
            case JumpConditionTypeEnum.PropertiesJump:
                ms.WriteString(PropertyName);
                ms.WriteInt(IntervalJumpTargets.Count);
                for (int i = 0; i < IntervalJumpTargets.Count; i++)
                {
                    IntervalJumpTargets[i].Serialize(ms);
                }
                break;
            case JumpConditionTypeEnum.ChargeJump:
                ms.WriteInt(IntervalJumpTargets.Count);
                for(int i = 0; i < IntervalJumpTargets.Count; i++)
                {
                    IntervalJumpTargets[i].Serialize(ms);
                }
                break;
        }
    }

    public override void Deserialize(EByte ms)
    {
        JumpConditionType = (JumpConditionTypeEnum)ms.ReadInt();
        switch(JumpConditionType)
        {
            case JumpConditionTypeEnum.DirectJump:
                JumpTarget = new JumpTarget();
                JumpTarget.Deserialize(ms);
                break;
            case JumpConditionTypeEnum.StimulateJump:
                JumpTarget = new JumpTarget();
                JumpTarget.Deserialize(ms);
                int stimulateCount = ms.ReadInt();
                StimulateJumpCondition = new List<StimulateTypeEnum>(stimulateCount);
                for(int i = 0; i < stimulateCount; i++)
                {
                    StimulateJumpCondition.Add((StimulateTypeEnum)ms.ReadInt());
                }
                break;
            case JumpConditionTypeEnum.LengthJump:
                JumpTarget = new JumpTarget();
                JumpTarget.Deserialize(ms);
                IsGreaterOrEqual = ms.ReadInt() == 1;
                LengthJumpCondition = FP.FromRaw(ms.ReadLong());
                break;
            case JumpConditionTypeEnum.HeightJump:
                JumpTarget = new JumpTarget();
                JumpTarget.Deserialize(ms);
                IsGreaterOrEqual = ms.ReadInt() == 1;
                HeightJumpCondition = FP.FromRaw(ms.ReadLong());
                break;
            case JumpConditionTypeEnum.StatusJump:
                JumpTarget = new JumpTarget();
                JumpTarget.Deserialize(ms);
                IsCheckSelf = ms.ReadInt() == 1;
                IsContainStatusJump = ms.ReadInt() == 1;
                int statusCount = ms.ReadInt();
                StatusIDs = new List<int>(statusCount);
                for(int i = 0; i < statusCount; i++)
                {
                    StatusIDs.Add(ms.ReadInt());
                }
                break;
            case JumpConditionTypeEnum.StateJump:
                JumpTarget = new JumpTarget();
                JumpTarget.Deserialize(ms);
                IsCheckSelf = ms.ReadInt() == 1;
                int statesCount = ms.ReadInt();
                StateMachineEnums = new List<StateEnum>(statesCount);
                for (int i = 0; i < statesCount; i++)
                {
                    StateMachineEnums.Add((StateEnum)ms.ReadInt());
                }
                break;
            case JumpConditionTypeEnum.PropertiesJump:
                PropertyName = ms.ReadString();
                int count = ms.ReadInt();
                IntervalJumpTargets = new List<IntervalJumpTarget>(count);
                for (int i = 0; i < count; i++)
                {
                    IntervalJumpTarget atarget = new IntervalJumpTarget();
                    atarget.Deserialize(ms);
                    IntervalJumpTargets.Add(atarget);
                }
                break;
            case JumpConditionTypeEnum.ChargeJump:
                int count1 = ms.ReadInt();
                IntervalJumpTargets = new List<IntervalJumpTarget>(count1);
                for(int i = 0; i < count1; i++)
                {
                    IntervalJumpTarget atarget = new IntervalJumpTarget();
                    atarget.Deserialize(ms);
                    IntervalJumpTargets.Add(atarget);
                }
                break;
        }
    }
}
